package com.sec.android.app.myfiles.fragment.search;

import android.app.SearchManager;
import android.app.SearchableInfo;
import android.content.Context;
import android.content.res.Configuration;
import android.graphics.Point;
import android.os.Handler;
import android.text.InputFilter;
import android.text.InputType;
import android.text.Spanned;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.util.SparseArray;
import android.view.Menu;
import android.view.MenuItem;
import android.view.MenuItem.OnActionExpandListener;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnFocusChangeListener;
import android.view.WindowManager;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputMethodManager;
import android.widget.LinearLayout;
import android.widget.SearchView;
import android.widget.SearchView.OnQueryTextListener;
import android.widget.TextView;
import android.widget.Toast;
import android.widget.Toolbar;

import com.sec.android.app.myfiles.R;
import com.sec.android.app.myfiles.activity.FileListActivity;
import com.sec.android.app.myfiles.facade.MyFilesFacade;
import com.sec.android.app.myfiles.fragment.AbsMyFilesFragment;
import com.sec.android.app.myfiles.info.AppConstants;
import com.sec.android.app.myfiles.info.AppFeatures;
import com.sec.android.app.myfiles.log.Log;
import com.sec.android.app.myfiles.log.SamsungAnalyticsLog;
import com.sec.android.app.myfiles.module.abstraction.FileRecord;
import com.sec.android.app.myfiles.module.abstraction.FileRecord.StorageType;
import com.sec.android.app.myfiles.module.search.SearchFileRecord;
import com.sec.android.app.myfiles.navigation.NavigationInfo;
import com.sec.android.app.myfiles.navigation.NavigationManager;
import com.sec.android.app.myfiles.util.EmoticonUtils;
import com.sec.android.app.myfiles.util.FileUtils;
import com.sec.android.app.myfiles.util.StorageMonitor;

public class SearchInputView extends LinearLayout implements OnQueryTextListener,
        OnActionExpandListener, OnFocusChangeListener, OnClickListener {
    private static SparseArray<SearchInputView> sSearchViewMap = new SparseArray<>();
    private static final int SCREEN_WIDTH_UNIT = 0;
    private static final int QUERY_UPDATE_TIME_NO_DELAY = 0;
    private static final int QUERY_UPDATE_TIME = 300;
    private boolean mIsSearchMenuExpanded = false;
    private int mScreenWidthDp = Configuration.SCREEN_WIDTH_DP_UNDEFINED;
    private int mSearchMaxWidth = 0;

    private Context mContext;
    private FileListActivity mActivity;
    private Menu mMenu;
    private MenuItem mSearchMenu;
    private NavigationInfo mNavigationInfo;
    private boolean mPreNavigationInfoSearchMode;
    private SearchView mSearchView;
    private TextView mTextView;
    private Toast mToast;
    private Handler mUpdateHandler = null;
    private String mQueryText;
    private boolean mSipVisible;

    public SearchInputView(Context context, AttributeSet attrs) {
        super(context, attrs);
        mContext = context;
    }

    public static SearchInputView getInstance(FileListActivity activity, Menu menu, NavigationInfo curInfo) {
        SearchInputView ret = sSearchViewMap.get(activity.getProcessId());
        if (ret == null) {
            MenuItem searchMenu = menu.findItem(R.id.menu_search);
            ret = (SearchInputView) searchMenu.getActionView();
            sSearchViewMap.put(activity.getProcessId(), ret);
        }
        ret.initSearchView(activity, menu, curInfo);
        return ret;
    }

    public static void clearInstance(int processId) {
        SearchInputView searchInputView = sSearchViewMap.get(processId);
        if (searchInputView != null) {
            sSearchViewMap.remove(processId);
        }
    }

    private void initSearchView(FileListActivity activity, Menu menu, NavigationInfo curInfo) {
        Log.d(this, "initSearchView()");
        mActivity = activity;
        mMenu = menu;
        mSearchMenu = menu.findItem(R.id.menu_search);
        mSearchMenu.setOnActionExpandListener(this);
        mNavigationInfo = curInfo;

        mSearchView = (SearchView) mSearchMenu.getActionView().findViewById(R.id.search_view);
        mSearchView.setOnQueryTextFocusChangeListener(this);
        mSearchView.setOnQueryTextListener(this);
        SearchManager searchManager = (SearchManager) mActivity.getSystemService(Context.SEARCH_SERVICE);
        try {
            SearchableInfo searchableInfo = searchManager.getSearchableInfo(mActivity.getComponentName());
            mSearchView.setSearchableInfo(searchableInfo);
        } catch (IllegalStateException e) {
            Log.e(this, "IllegalStateException:" + e.toString());
        }

        int textViewId = mSearchView.getContext().getResources().getIdentifier("android:id/search_src_text", null, null);
        mTextView = (TextView) mSearchView.findViewById(textViewId);
        mTextView.setFilters(new InputFilter[]{getTextFilter(), getEmoticonFilter()});
        mTextView.setImeOptions(mTextView.getImeOptions() | EditorInfo.IME_FLAG_NO_EXTRACT_UI | EditorInfo.IME_ACTION_SEARCH);
        mTextView.setOnClickListener(this);
        mTextView.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_FLAG_AUTO_COMPLETE);
        StringBuilder imeOptionsString = new StringBuilder();
        imeOptionsString.append(AppConstants.ImeOptions.EMOTICON_OFF).append(";").append(AppConstants.ImeOptions.VOICEINPUT_OFF);
        mTextView.setPrivateImeOptions(imeOptionsString.toString());

        mQueryText = "";

        if (AppFeatures.isTabletUIMode()) {
            mSearchView.setIconifiedByDefault(false);
            mSearchMenu.setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS);
            refreshSearchViewWidth(getResources().getConfiguration());
            mIsSearchMenuExpanded = true;
            mNavigationInfo.setIsSearchMode(true);
            setQuery();
        } else {
            setSearchViewPadding();
            mSearchView.setIconifiedByDefault(true);
            mSearchView.setMaxWidth(mActivity.getResources().getDimensionPixelSize(R.dimen.search_view_max_width));
            if (mNavigationInfo.getIsSearchMode()) {
                expandSearchMenu();
            } else {
                collapseSearchMenu();
            }
            mIsSearchMenuExpanded = mNavigationInfo.getIsSearchMode();
        }

        if (mUpdateHandler == null) {
            mUpdateHandler = new Handler();
        }
    }

    private void setSearchViewPadding() {
        int layoutId = mContext.getResources().getIdentifier("android:id/search_plate", null, null);
        LinearLayout searchPlatLayout = (LinearLayout) mSearchView.findViewById(layoutId);
        LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) searchPlatLayout.getLayoutParams();
        params.setMarginStart(0);
        searchPlatLayout.setLayoutParams(params);
    }

    @Override
    public boolean onQueryTextChange(String text) {
        Log.d(this, "onQueryTextChange : " + text);
        if (mQueryText == null || !mQueryText.equals(text)) {
            mQueryText = text;

            if (mUpdateHandler != null) {
                int delay = TextUtils.isEmpty(mQueryText) ? QUERY_UPDATE_TIME_NO_DELAY : QUERY_UPDATE_TIME;
                mUpdateHandler.removeCallbacksAndMessages(mQueryUpdateRunnable);
                mUpdateHandler.postDelayed(mQueryUpdateRunnable, delay);
            }
        }
        return true;
    }

    private Runnable mQueryUpdateRunnable = new Runnable() {
        @Override
        public void run() {
            if (mQueryText.trim().isEmpty()) {
                NavigationManager navigationManager = NavigationManager.getInstance(mActivity.getProcessId());
                if (navigationManager.getDepth() >= 1 && mNavigationInfo.getStorageType() == StorageType.Search) {
                    NavigationInfo curInfo = navigationManager.leave();
                    if (curInfo == null) {
                        MyFilesFacade.goHome(mActivity.getProcessId(), null, mContext);
                    }
                }
            }
        }
    };

    @Override
    public boolean onQueryTextSubmit(String text) {
        Log.d(this, "onQueryTextSubmit : " + text);
        InputMethodManager inputMethodManager = (InputMethodManager) mActivity.getSystemService(Context.INPUT_METHOD_SERVICE);
        MyFilesFacade.searchRecords(mActivity.getProcessId(), null, text);
        mTextView.clearFocus();
        return true;
    }

    @Override
    public boolean onMenuItemActionExpand(MenuItem item) {
        Log.d(this, "onMenuItemActionExpand()");
        SamsungAnalyticsLog.sendLog(mActivity.getProcessId(), SamsungAnalyticsLog.Event.SEARCH, null);
        mSearchView.setIconified(false);
        mNavigationInfo.setIsSearchMode(true);
        mIsSearchMenuExpanded = true;
        setQuery();
        mMenu.setGroupVisible(R.id.menu_group_list, AppFeatures.isTabletUIMode());
        setMenuVisibility(R.id.menu_toggle_list_type, AppFeatures.isTabletUIMode());
        updateSip(true, AppFeatures.SIP_APPEARANCE_DELAY);
        return true;
    }

    @Override
    public boolean onMenuItemActionCollapse(MenuItem item) {
        Log.d(this, "onMenuItemActionCollapse()");
        SamsungAnalyticsLog.sendLog(mActivity.getProcessId(), SamsungAnalyticsLog.Event.NAVIGATE_UP, null);
        mSearchView.setIconified(true);
        mNavigationInfo.setIsSearchMode(false);
        mIsSearchMenuExpanded = false;
        mMenu.setGroupVisible(R.id.menu_group_list, true);
        setMenuVisibility(R.id.menu_toggle_list_type, true);
        mActivity.invalidateOptionsMenu();
        return true;
    }

    @Override
    public void onFocusChange(View view, boolean hasFocus) {
        Log.d(this, "onFocusChange(): hasFocus - " + hasFocus);
        if (mNavigationInfo != null) {
            AbsMyFilesFragment curFragment = mNavigationInfo.getCurFragment();
            if (curFragment != null && curFragment.isDragtStarted()) {
                mTextView.clearFocus();
            } else {
                updateSip(hasFocus, AppFeatures.SIP_APPEARANCE_DELAY);
            }
        }
    }

    public void updateSip(boolean visible, int delay) {
        if (mUpdateHandler != null) {
            mUpdateHandler.removeCallbacksAndMessages(mSipUpdateRunnable);

            mSipVisible = visible;
            delay = visible ? delay : 0;

            mUpdateHandler.postDelayed(mSipUpdateRunnable, delay);
        }
    }

    public boolean isSipVisible() {
        return mSipVisible;
    }

    private Runnable mSipUpdateRunnable = new Runnable() {
        @Override
        public void run() {
            InputMethodManager inputMethodManager = (InputMethodManager) mActivity.getSystemService(Context.INPUT_METHOD_SERVICE);
            if (mSipVisible) {
                inputMethodManager.showSoftInput(mTextView, InputMethodManager.SHOW_IMPLICIT);
            } else {
                if (mTextView.hasFocus()) {
                    mTextView.clearFocus();
                } else {
                    //TODO HYL 输入法
                    /*
                    if (AppFeatures.SCROLL_DA_ENABLED) {
                        inputMethodManager.semMinimizeSoftInput(mSearchView.getWindowToken(), 22);
                    } else {
                        if (inputMethodManager.semIsInputMethodShown()) {
                            inputMethodManager.semForceHideSoftInput();
                        }
                    }
                    */
                }
            }
        }
    };

    @Override
    public void onClick(View v) {
        updateSip(true, 0);
    }

    public void setQuery(String query, boolean submit) {
        if (mSearchView != null && mIsSearchMenuExpanded) {
            Log.d(this, "setQuery(): " + query);
            mQueryText = query;
            mSearchView.setQuery(query, submit);
        }
    }

    private void setQuery() {
        mQueryText = mQueryText != null ? mQueryText.trim() : "";
        if (mNavigationInfo != null && mNavigationInfo.getStorageType() == StorageType.Search) {
            FileRecord record = mNavigationInfo.getCurRecord();
            if (record instanceof SearchFileRecord) {
                String query = ((SearchFileRecord) record).getSearchedName();
                boolean isNeedSetQuery = mQueryText == null || !mQueryText.equals(query);
                if ((mPreNavigationInfoSearchMode) && isNeedSetQuery) {
                    setQuery(query, false);
                }
            }
        } else {
            boolean isNeedSetQuery = mQueryText == null || !mQueryText.isEmpty();
            if (isNeedSetQuery) {
                setQuery("", false);
            }
        }
        if (mTextView != null && !AppFeatures.isTabletUIMode()) {
            mTextView.requestFocus();
        }
    }

    private void expandSearchMenu() {
        if (mSearchMenu != null) {
            mSearchMenu.expandActionView();
        }

        if (mTextView != null && AppFeatures.isTabletUIMode()) {
            mTextView.requestFocus();
        }
    }

    public void collapseSearchMenu() {
        if (mSearchMenu != null && mSearchMenu.isActionViewExpanded()) {
            mSearchMenu.collapseActionView();
        }
    }

    private void setMenuVisibility(int menuId, boolean visible) {
        MenuItem menuItem = mMenu.findItem(menuId);
        if (menuItem != null) {
            menuItem.setVisible(visible);
        }
    }

    private InputFilter getTextFilter() {
        return new InputFilter.LengthFilter(AppConstants.MAX_INPUT_LENGTH) {
            @Override
            public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend) {
                CharSequence ret = super.filter(source, start, end, dest, dstart, dend);
                if (ret != null) {
                    showToast();
                }
                return ret;
            }
        };
    }

    private InputFilter getEmoticonFilter() {
        return new InputFilter() {
            @Override
            public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend) {
                if (EmoticonUtils.hasEmoticon(source)) {
                    Toast.makeText(mContext, mContext.getString(R.string.invalid_character), Toast.LENGTH_SHORT).show();
                    return "";
                } else {
                    return source;
                }
            }
        };
    }

    private void showToast() {
        boolean isAlreadyShown = (mToast != null) && (mToast.getView() != null) && (mToast.getView().isShown());
        if (isAlreadyShown) {
            return;
        }
        if (mToast == null) {
            mToast = Toast.makeText(mContext, mContext.getString(R.string.max_char_reached_msg, AppConstants.MAX_INPUT_LENGTH), Toast.LENGTH_SHORT);
        } else {
            mToast.setText(mContext.getString(R.string.max_char_reached_msg, AppConstants.MAX_INPUT_LENGTH));
        }
        mToast.show();
    }

    public void onNavigationChanged(NavigationInfo preInfo, NavigationInfo curInfo) {
        mNavigationInfo = curInfo;
        if (preInfo != null) {
            boolean isPreSearchMode = preInfo.getIsSearchMode();
            mPreNavigationInfoSearchMode = (AppFeatures.isTabletUIMode() && !preInfo.isSelectMode()) == isPreSearchMode;
        } else {
            mPreNavigationInfoSearchMode = false;
        }

        setQuery();

        if (mNavigationInfo != null) {
            if (AppFeatures.isTabletUIMode() && mNavigationInfo.getCurFragment() != null
                    && mNavigationInfo.getCurFragment().getActionModeType() == AbsMyFilesFragment.ActionModeType.NORMAL) {
                mNavigationInfo.setIsSearchMode(true);
            } else {
                if (mNavigationInfo.getIsSearchMode()) {
                    if (!mIsSearchMenuExpanded) {
                        expandSearchMenu();
                    }
                } else {
                    if (mIsSearchMenuExpanded) {
                        InputMethodManager inputMethodManager = (InputMethodManager) mActivity.getSystemService(Context.INPUT_METHOD_SERVICE);
                        collapseSearchMenu();
                    }
                }
            }
        }
    }

    public boolean isSearchMenuExpanded() {
        return mIsSearchMenuExpanded;
    }

    public void dispatchSearchKey() {
        if (mNavigationInfo != null && mNavigationInfo.isNormalMode() && !mNavigationInfo.isUsbStorage()) {
            FileRecord record = mNavigationInfo.getCurRecord();
            if (record != null && !StorageMonitor.isRemovedExtSDCard(record.getFullPath())
                    && (!FileUtils.isEmptyStorage(mNavigationInfo, mNavigationInfo.getCurFragment()) || AppFeatures.isTabletUIMode())) {
                expandSearchMenu();
            }
        }
    }

    public void refreshSearchViewWidth(Configuration newConfig) {
        if (AppFeatures.isTabletUIMode()) {
            if (isScreenWidthDpChanged(newConfig) || mSearchMaxWidth == 0) {
                if (mSearchView != null) {
                    WindowManager wm = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
                    Point size = new Point();
                    wm.getDefaultDisplay().getSize(size);
                    int actionBarTitleWidth = getActionBarTitleWidth();
                    int actionBarTitleMaxWidth = mContext.getResources().getDimensionPixelSize(R.dimen.dexmode_expanded_myfiles_title_width);
                    if (actionBarTitleWidth == 0 || actionBarTitleWidth > actionBarTitleMaxWidth) {
                        actionBarTitleWidth = actionBarTitleMaxWidth;
                    }
                    mSearchMaxWidth = size.x - mContext.getResources().getDimensionPixelSize(R.dimen.dexmode_expanded_search_view_margin) - actionBarTitleWidth;
                    Log.d(this, "refreshSearchViewWidth():" + mSearchMaxWidth);
                    mSearchView.setMaxWidth(mSearchMaxWidth);
                }
            } else {
                mSearchView.setMaxWidth(mSearchMaxWidth);
            }
        }
    }

    private int getActionBarTitleWidth() {
        int nRet = 0;
        int id = mActivity.getResources().getIdentifier("action_bar", "id", "android");
        View actionBar = mActivity.findViewById(id);
        if (actionBar instanceof Toolbar) {
            Toolbar toolbar = (Toolbar) actionBar;
            for (int i = 0; i < toolbar.getChildCount(); i++) {
                if (toolbar.getChildAt(i) instanceof TextView) {
                    TextView titleTextView = (TextView) toolbar.getChildAt(i);
                    if (titleTextView != null) {
                        nRet = titleTextView.getMeasuredWidth();
                    }
                    break;
                }
            }
        }
        return nRet;
    }

    private boolean isScreenWidthDpChanged(Configuration configuration) {
        boolean ret = false;
        if (Math.abs(mScreenWidthDp - configuration.screenWidthDp) > SCREEN_WIDTH_UNIT) {
            ret = true;
            mScreenWidthDp = configuration.screenWidthDp;
            Log.d(this, "isScreenWidthDpChanged()");
        }
        return ret;
    }
}